package com.zx.deploy.common.utils;

import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.apache.commons.lang.StringUtils;

/**
 * 描述：${DESCRIPTION}
 *
 * @创建人： shuyizhi
 * @创建时间： 2017-09-14 10:23
 **/

public class DatetimeUtil {
    /**
     * 私有空参构造器
     */
    private DatetimeUtil() {
        super();
    }

    /**
     * 自定义默认时间格式化模板串常量<br>
     * yyyy-MM-dd HH:mm:ss
     */
    private static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * 自定义默认时间格式化模板串常量<br>
     * yyyy-MM-dd
     */
    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    
    private static final TimeZone defult= TimeZone.getTimeZone("GMT+8");

    /**
     * 获取指定日期格式的日期格式化处理对象
     *
     * @param format 指定的时间格式
     * @return
     */
    public static SimpleDateFormat getSimpleDateFormat(String format) {
    	SimpleDateFormat sdf = new SimpleDateFormat(format);
		sdf.setTimeZone(defult);
        return sdf;
    }

    /**
     * 获取指定格式化的对象字符串
     *
     * @param format 格式化模板串
     * @param obj    需格式化的对象
     * @return
     */
    private static String getDateFormatStr(String format, Object obj) {

        return getSimpleDateFormat(format).format(obj);
    }

    /**
     * 获取系统当前时间毫秒数
     *
     * @return 系统当前时间毫秒数
     */
    public static long getCurrentTimeMillis() {

        return System.currentTimeMillis();
    }

    /**
     * 获取指定格式化的系统当前时间串
     *
     * @param format 指定的时间格式
     * @return 指定格式的当前时间串
     * @throws IllegalArgumentException
     */
    public static String getCurrentDateTime(String format) {

        try {
            return getDateFormatStr(format, new Date());
        } catch (Exception e) {
            throw new IllegalArgumentException(MessageFormat.format("非法参数异常：[{0}]", format));
        }
    }

    /**
     * 获取默认格式化的系统当前时间串<br>
     * 例如： 2017-08-30 18:49:09
     *
     * @return
     * @throws Exception
     */
    public static String getDefaultCurrentDateTime() {

        return getCurrentDateTime(DEFAULT_FORMAT);
    }

    /**
     * 获取指定毫秒数之前的日期时间串 默认获取时间格式如：2017-08-30 18:49:09
     *
     * @param timeDiff 指定毫秒数
     * @return
     */
    public static String getDesignatedDate(long timeDiff) {
        return getDateFormatStr(DEFAULT_FORMAT, getCurrentTimeMillis() - timeDiff);
    }

    /**
     * 获取指定毫秒数之前的日期串(指定获取时间格式)
     *
     * @param timeDiff 指定毫秒数
     * @param format   指定获取的时间格式串模板
     * @return
     */
    public static String getDesignatedDate(long timeDiff, String format) {
        return getDateFormatStr(format, getCurrentTimeMillis() - timeDiff);
    }

    /**
     * 获取当前时间前n天的日期时间串<br>
     * 默认获取时间格式如：2017-08-30 18:49:09
     *
     * @param n 间隔天数，不区分正负整数
     * @return
     */
    public static String getOtherDayTime(int n) {
        Calendar cal = Calendar.getInstance(defult);
        cal.add(Calendar.DATE, n > 0 ? -n : n);
        return getDateFormatStr(DEFAULT_FORMAT, cal.getTime());
    }

    /**
     * 获取当前时间前n天的日期时间串(指定获取时间格式)<br>
     *
     * @param n      间隔天数，不区分正负整数
     * @param format 指定获取的时间格式串模板
     * @return
     */
    public static String getOtherDayTime(int n, String format) {

        Calendar cal = Calendar.getInstance(defult);
        cal.add(Calendar.DATE, n > 0 ? -n : n);

        return getDateFormatStr(format, cal.getTime());
    }

    /**
     * 获取当前日期后n天的日期时间串<br>
     * 默认获取时间格式如：：2017-08-30 18:49:09
     *
     * @param n 间隔天数，不区分正负整数
     * @return
     */
    public static String getAfterDays(int n) {

        Calendar cal = Calendar.getInstance(defult);
        cal.add(Calendar.DATE, n > 0 ? n : -n);

        return getDateFormatStr(DEFAULT_FORMAT, cal.getTime());
    }

    /**
     * 获取当前日期后n天的日期时间串(指定获取时间格式)<br>
     *
     * @param n      间隔天数，不区分正负整数
     * @param format 指定获取的时间格式串模板
     * @return
     */
    public static String getAfterDays(int n, String format) {

        Calendar cal = Calendar.getInstance(defult);
        cal.add(Calendar.DATE, n > 0 ? n : -n);

        return getDateFormatStr(format, cal.getTime());
    }

    /**
     * 日期转换成默认格式(yyyy-MM-dd HH:mm:ss)字符串<br>
     * 例如：2017-08-30 09:55:01
     *
     * @param date 日期实例对象
     * @return
     */
    public static String dateToString(Date date) {

        return getDateFormatStr(DEFAULT_FORMAT, date);
    }

    /**
     * 日期转换成指定格式字符串<br>
     *
     * @param date 日期实例对象
     * @return
     */
    public static String dateToString(Date date, String format) {

        return getDateFormatStr(format, date);
    }

    /**
     * yyyy-MM-dd HH:mm:ss 格式的字符串转换日期
     *
     * @param dateStr 日期字符串对象,格式需 yyyy-MM-dd HH:mm:ss
     * @return
     * @throws ParseException
     */
    public static Date stringToDate(String dateStr) throws ParseException {

        if (StringUtils.isBlank(dateStr))
            return null;

        return getSimpleDateFormat(DEFAULT_FORMAT).parse(dateStr);
    }

    /**
     * 日期字符串转换指定格式的日期串
     *
     * @param dateStr 日期字符串对象
     * @param format  指定日期格式模板串(指定的格式需参数日期字符串对象匹配)<br>
     *                如：dateStr=2017-08-30; format=yyyy-MM-dd
     * @return
     * @throws ParseException
     */
    public static Date stringToDate(String dateStr, String format) throws ParseException {

        if (StringUtils.isBlank(dateStr))
            return null;

        return getSimpleDateFormat(format).parse(dateStr);
    }

    /**
     * 获取指定日期的下一天日期（默认处理日期格式为 yyyy-MM-dd）
     *
     * @param dateStr 指定的日期时间串
     * @return
     * @throws ParseException
     */
    public static String nextDay(String dateStr) throws ParseException {

        SimpleDateFormat sdf = getSimpleDateFormat(DEFAULT_DATE_FORMAT);

        Calendar cd = Calendar.getInstance(defult);
        cd.setTime(sdf.parse(dateStr));
        cd.add(Calendar.DATE, 1);// 增加一天

        return sdf.format(cd.getTime());
    }

    /**
     * 获取指定日期的下一天日期
     *
     * @param dateStr 指定的日期时间串
     * @param format  指定的日期时间串格式模板<br>
     *                如：startDate=2017-08-30; format=yyyy-MM-dd
     * @return
     * @throws ParseException
     */
    public static String nextDay(String dateStr, String format) throws ParseException {

        SimpleDateFormat sdf = getSimpleDateFormat(format);

        Calendar cd = Calendar.getInstance(defult);
        cd.setTime(sdf.parse(dateStr));
        cd.add(Calendar.DATE, 1);// 增加一天

        return sdf.format(cd.getTime());
    }

    /**
     * 获取指定日期的昨天日期（默认处理日期格式为 yyyy-MM-dd）
     *
     * @param dateStr 指定的日期时间串
     * @return
     * @throws ParseException
     */
    public static String yesterDay(String dateStr) throws ParseException {

        SimpleDateFormat sdf = getSimpleDateFormat(DEFAULT_DATE_FORMAT);

        Calendar cd = Calendar.getInstance(defult);
        cd.setTime(sdf.parse(dateStr));
        cd.add(Calendar.DATE, -1);// 减一天

        return sdf.format(cd.getTime());
    }

    /**
     * 获取指定日期的昨天日期
     *
     * @param dateStr 指定的日期时间串
     * @param format  指定的日期时间串格式模板<br>
     *                如：startDate=2017-08-30; format=yyyy-MM-dd
     * @return
     * @throws ParseException
     */
    public static String yesterDay(String dateStr, String format) throws ParseException {

        SimpleDateFormat sdf = getSimpleDateFormat(format);

        Calendar cd = Calendar.getInstance(defult);
        cd.setTime(sdf.parse(dateStr));
        cd.add(Calendar.DATE, -1);// 减一天

        return sdf.format(cd.getTime());
    }

    /**
     * 在指定日期上增加数个整月
     *
     * @param date 指定的日期对象
     * @param n    增加的月数(不区分正负整数)
     * @return
     */
    public static Date addMonth(Date date, int n) {

        Calendar cal = Calendar.getInstance(defult);
        cal.setTime(date);
        cal.add(Calendar.MONTH, n < 0 ? -n : n);

        return cal.getTime();
    }

    /**
     * 获取结束时间和开始时间的天数差值
     *
     * @param beginDateStr 开始时间串
     * @param endDateStr   结束时间串
     *                     <p>
     *                     <pre>
     *                                                             结束时间 - 开始时间 = 天数差值
     *                                                                        </pre>
     * @return
     * @throws ParseException
     */
    public static long getDaySub(String beginDateStr, String endDateStr) throws ParseException {

        Date beginDate = stringToDate(beginDateStr, DEFAULT_DATE_FORMAT);
        Date endDate = stringToDate(endDateStr, DEFAULT_DATE_FORMAT);
        // 计算得到相差的天数
        return (endDate.getTime() - beginDate.getTime()) / (24 * 60 * 60 * 1000);
    }

    /**
     * 计算结束时间和开始时间串的时间差值<br>
     * 如： timeSubtract("2017-08-30","2017-08-31","yyyy-MM-dd") = 1天0小时0分0秒
     *
     * @param beginDateStr 开始时间串
     * @param endDateStr   结束时间串
     * @param format       指定两个日期运算的格式模板串
     * @return
     * @throws Exception
     */
    public static String timeSubtract(String beginDateStr, String endDateStr, String format) throws Exception {

        Date begin = stringToDate(beginDateStr, format);
        Date end = stringToDate(endDateStr, format);
        // 除以1000是为了转换成秒
        long between = (end.getTime() - begin.getTime()) / 1000;
        long day = between / (24 * 3600);
        long hour = between % (24 * 3600) / 3600;
        long minute = between % 3600 / 60;
        long second = between % 60;

        return new StringBuilder().append(day).append("天").append(hour).append("小时").append(minute).append("分")
                .append(second).append("秒").toString();
    }
    
    
    /**
     * 计算结束时间和开始时间串的时间差值<br>
     * 如： timeSubtract("2017-08-30","2017-08-31","yyyy-MM-dd") = 1天0小时0分0秒
     *
     * @param beginDateStr 开始时间串
     * @param endDateStr   结束时间串
     * @param format       指定两个日期运算的格式模板串
     * @return
     * @throws Exception
     */
    public static String timeSubtract(long begin, long end) throws Exception {
        // 除以1000是为了转换成秒
        long between = (end - begin) / 1000;
        long day = between / (24 * 3600);
        long hour = between % (24 * 3600) / 3600;
        long minute = between % 3600 / 60;
        long second = between % 60;

        return new StringBuilder().append(day).append("天").append(hour).append("小时").append(minute).append("分")
                .append(second).append("秒").toString();
    }

    /**
     * 时间戳转换为日期格式字符串（格式：yyyy-MM-dd HH:mm:ss）
     *
     * @param time 时间戳
     * @return 日期格式字符串
     */
    public static String timeStamp2Date(long time) {

        return getSimpleDateFormat(DEFAULT_FORMAT).format(new Date(time));
    }

    /**
     * 当前日期转为时间戳
     *
     * @param date 当前日期实例
     * @return 当前日期的时间戳
     * @throws ParseException 转换异常
     */
    public static Long Date2TimeStamp(Date date) throws ParseException {

        SimpleDateFormat sdf = getSimpleDateFormat(DEFAULT_FORMAT);

        return sdf.parse(sdf.format(date)).getTime();
    }

    /**
     * 两个时间比较
     * <p>
     * <pre>
     * 若:date1 > date2 = 1; date1 < date2 = -1; date1 == date2 = 0
     * </pre>
     *
     * @param date1 时间对象1
     * @param date2 时间对象2
     * @return int
     */
    public static int compareDate(Date date1, Date date2) {

        if (date1.getTime() > date2.getTime()) {
            return 1;
        } else if (date1.getTime() < date2.getTime()) {
            return -1;
        }
        return 0;
    }

    /**
     * 获取当前年
     *
     * @return
     */
    public static int getCurrYear() {

        return Calendar.getInstance(defult).get(Calendar.YEAR);
    }

    /**
     * 获取当前月份
     *
     * @return
     */
    public static int getCurrMonth() {

        return Calendar.getInstance(defult).get(Calendar.MONTH) + 1;
    }

    /**
     * 获取当前日
     *
     * @return
     */
    public static int getCurrDay() {

        return Calendar.getInstance(defult).get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取当前周
     *
     * @return
     */
    public static int getCurrWeek() {

        return Calendar.getInstance(defult).get(Calendar.DAY_OF_WEEK) - 1;
    }

    /**
     * 获取当前小时
     *
     * @return
     */
    public static int getCurrHour() {

        return Calendar.getInstance(defult).get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 获取当前分钟数
     *
     * @return
     */
    public static int getCurrMinute() {

        return Calendar.getInstance(defult).get(Calendar.MINUTE);
    }

    /**
     * 获取当前秒钟数
     *
     * @return
     */
    public static int getCurrSecond() {

        return Calendar.getInstance(defult).get(Calendar.SECOND);
    }
}
